home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * lathe.c
- *
- * This module implements functions that manipulate lathes.
- *
- * This module was written by Dieter Bayer [DB].
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- /****************************************************************************
- *
- * Explanation:
- *
- * The lathe primitive is defined by a set of points in 2d space which
- * are interpolated by linear, quadratic, or cubic splines. The resulting
- * 2d curve is rotated about an axis to form the final lathe object.
- *
- * All calculations are done in the object's (u,v,w)-coordinate system
- * with the (w)-axis being the rotation axis.
- *
- * One spline segment in the (r,w)-plane is given by the equations
- *
- * fw(t) = Aw * t^3 + Bw * t^2 + Cw * t + Dw and
- * fr(t) = Ar * t^3 + Br * t^2 + Cr * t + Dr,
- *
- * with the parameter t ranging from 0 to 1 and r = sqrt(u*u+v*v).
- *
- * To intersect a ray R = P + k * D transformed into the object's
- * coordinate system with the lathe object, the equations
- *
- * (Pu + k * Du)^2 + (Pv + k * Dv)^2 = (fr(t))^2
- * (Pw + k * Dw) = fw(t)
- *
- * have to be solved for t. For valid intersections (0 <= t <= 1)
- * the corresponding k can be calculated from one of the above equations.
- *
- * Note that the degree of the polynomal to solve is two times the
- * degree of the spline segments used.
- *
- * Note that Pu, Pv, Pw and Du, Dv, Dw denote the coordinates
- * of the vectors P and D.
- *
- * Syntax:
- *
- * lathe
- * {
- * [ linear_spline | quadratic_spline | cubic_spline ]
- *
- * number_of_points,
- *
- * <P[0]>, <P[1], ..., <P[n-1]>
- *
- * [ sturm ]
- * }
- *
- * Note that the P[i] are 2d vectors.
- *
- * Linear interpolation is used by default. In this case all n Points
- * are used. In the quadratic case the first point is used to determine
- * the derivates at the starting point P[1]. In the cubic case
- * the first and last points are used to determine the derivatives at
- * the starting point P[1] and ending point P[n-2].
- *
- * To get a closed (and smooth) curve you have make sure that
- *
- * P[0] = P[n-1] in the linear case,
- *
- * P[0] = P[n-2] and P[1] = P[n-1] in the quadratic case, and
- *
- * P[0] = P[n-3] and P[1] = P[n-2] and P[2] = P[n-1] in the cubic case.
- *
- * Note that the x coordinate of a point corresponds to the r coordinate
- * and the y coordinate to the w coordinate;
- *
- * ---
- *
- * Ideas for the lathe were taken from:
- *
- * P. Burger and D. Gillies, "Rapid Ray Tracing of General Surfaces
- * of Revolution", New Advances in Computer Graphics, Proceedings
- * of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.),
- * Springer, ..., pp. 523-531
- *
- * P. Burger and D. Gillies, "Swept Surfaces", Interactive Computer
- * Graphics, Addison-Wesley, 1989, pp. 376-380
- *
- * ---
- *
- * Jun 1994 : Creation. [DB]
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "povray.h"
- #include "vector.h"
- #include "povproto.h"
- #include "bbox.h"
- #include "lathe.h"
- #include "polysolv.h"
- #include "matrices.h"
- #include "objects.h"
- #include "torus.h"
-
-
-
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
-
- /* Minimal intersection depth for a valid intersection. */
-
- #define DEPTH_TOLERANCE 1.0e-4
-
- /* Max. number of intersecions per spline segment. */
-
- #define MAX_INTERSECTIONS_PER_SEGMENT 4
-
-
-
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
-
- static int intersect_lathe PARAMS((RAY *Ray, LATHE *Lathe, ISTACK *Depth_Stack));
- static int All_Lathe_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
- static int Inside_Lathe PARAMS((VECTOR point, OBJECT *Object));
- static void Lathe_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
- static void *Copy_Lathe PARAMS((OBJECT *Object));
- static void Translate_Lathe PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Rotate_Lathe PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Scale_Lathe PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Transform_Lathe PARAMS((OBJECT *Object, TRANSFORM *Trans));
- static void Invert_Lathe PARAMS((OBJECT *Object));
- static void Destroy_Lathe PARAMS((OBJECT *Object));
-
- static int test_hit PARAMS((LATHE *, RAY *, ISTACK *, DBL, DBL, int));
-
-
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
-
- static METHODS Lathe_Methods =
- {
- All_Lathe_Intersections,
- Inside_Lathe, Lathe_Normal,
- Copy_Lathe,
- Translate_Lathe, Rotate_Lathe,
- Scale_Lathe, Transform_Lathe, Invert_Lathe, Destroy_Lathe
- };
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * All_Lathe_Intersections
- *
- * INPUT
- *
- * Object - Object
- * Ray - Ray
- * Depth_Stack - Intersection stack
- *
- * OUTPUT
- *
- * Depth_Stack
- *
- * RETURNS
- *
- * int - TRUE, if a intersection was found
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Determine ray/lathe intersection and clip intersection found.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- * Oct 1996 : Changed code to include faster version. [DB]
- *
- ******************************************************************************/
-
- static int All_Lathe_Intersections(Object, Ray, Depth_Stack)
- OBJECT *Object;
- RAY *Ray;
- ISTACK *Depth_Stack;
- {
- Increase_Counter(stats[Ray_Lathe_Tests]);
-
- if (intersect_lathe(Ray, (LATHE *)Object, Depth_Stack))
- {
- Increase_Counter(stats[Ray_Lathe_Tests_Succeeded]);
-
- return(TRUE);
- }
-
- return(FALSE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_lathe
- *
- * INPUT
- *
- * Ray - Ray
- * Lathe - Lathe
- * Intersection - Lathe intersection structure
- *
- * OUTPUT
- *
- * Intersection
- *
- * RETURNS
- *
- * int - Number of intersections found
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Determine ray/lathe intersection.
- *
- * NOTE: The curve is rotated about the y-axis!
- * Order of the polynomial must not be used!
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- * Oct 1996 : Changed code to include faster version. [DB]
- *
- ******************************************************************************/
-
- static int intersect_lathe(Ray, Lathe, Depth_Stack)
- RAY *Ray;
- LATHE *Lathe;
- ISTACK *Depth_Stack;
- {
- int cnt;
- int found, j, n1, n2;
- DBL k, len, r, m, w, Dy2, r0;
- DBL x1[7], x2[3], y1[6], y2[2];
- DBL best;
- VECTOR P, D;
- BCYL_INT *intervals;
- LATHE_SPLINE_ENTRY *Entry;
-
- /* Transform the ray into the lathe space. */
-
- MInvTransPoint(P, Ray->Initial, Lathe->Trans);
-
- MInvTransDirection(D, Ray->Direction, Lathe->Trans);
-
- VLength(len, D);
-
- VInverseScaleEq(D, len);
-
- /* Test if ray misses lathe's cylindrical bound. */
-
- #ifdef LATHE_EXTRA_STATS
- Increase_Counter(stats[Lathe_Bound_Tests]);
- #endif
-
- if (((D[Y] >= 0.0) && (P[Y] > Lathe->Height2)) ||
- ((D[Y] <= 0.0) && (P[Y] < Lathe->Height1)) ||
- ((D[X] >= 0.0) && (P[X] > Lathe->Radius2)) ||
- ((D[X] <= 0.0) && (P[X] < -Lathe->Radius2)))
- {
- return(FALSE);
- }
-
- /* Get distance r0 of the ray from rotation axis (i.e. y axis). */
-
- r0 = fabs(P[X] * D[Z] - P[Z] * D[X]);
-
- r = D[X] * D[X] + D[Z] * D[Z];
-
- if (r > 0.0)
- {
- r0 /= sqrt(r);
- }
-
- /* Test if ray misses lathe's cylindrical bound. */
-
- if (r0 > Lathe->Radius2)
- {
- return(FALSE);
- }
-
- /* Intersect all cylindrical bounds. */
-
- if ((cnt = Intersect_BCyl(Lathe->Spline->BCyl, P, D)) == 0)
- {
- return(FALSE);
- }
-
- #ifdef LATHE_EXTRA_STATS
- Increase_Counter(stats[Lathe_Bound_Tests_Succeeded]);
- #endif
-
- /* Precalculate some constants that are ray-dependant only. */
-
- m = D[X] * P[X] + D[Z] * P[Z];
-
- Dy2 = D[Y] * D[Y];
-
- /* Step through the list of intersections. */
-
- found = FALSE;
-
- best = BOUND_HUGE;
-
- intervals = Lathe->Spline->BCyl->intervals;
-
- for (j = 0; j < cnt; j++)
- {
- /* Get current segment. */
-
- Entry = &Lathe->Spline->Entry[intervals[j].n];
-
- /* If we already have the best intersection we may exit. */
-
- if (!(Lathe->Type & IS_CHILD_OBJECT) && (intervals[j].d[0] > best))
- {
- break;
- }
-
- /* Init number of roots found. */
-
- n1 = 0;
-
- /* Intersect segment. */
-
- switch (Lathe->Spline_Type)
- {
- /***********************************************************************
- * Linear spline.
- ************************************************************************/
-
- case LINEAR_SPLINE:
-
- /* Solve 2th order polynomial. */
-
- x1[0] = Entry->C[Y] * Entry->C[Y] * r - Entry->C[X] * Entry->C[X] * Dy2;
-
- x1[1] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
-
- x1[2] = (Entry->D[Y] - P[Y]) * ((Entry->D[Y] - P[Y]) * r + 2.0 * D[Y] * m) + Dy2 * (P[X] * P[X] + P[Z] * P[Z] - Entry->D[X] * Entry->D[X]);
-
- n1 = Solve_Polynomial(2, x1, y1, FALSE, 0.0);
-
- break;
-
- /***********************************************************************
- * Quadratic spline.
- ************************************************************************/
-
- case QUADRATIC_SPLINE:
-
- /* Solve 4th order polynomial. */
-
- x1[0] = Entry->B[Y] * Entry->B[Y] * r - Entry->B[X] * Entry->B[X] * Dy2;
-
- x1[1] = 2.0 * (Entry->B[Y] * Entry->C[Y] * r - Entry->B[X] * Entry->C[X] * Dy2);
-
- x1[2] = r * (2.0 * Entry->B[Y] * (Entry->D[Y] - P[Y]) + Entry->C[Y] * Entry->C[Y]) + 2.0 * Entry->B[Y] * D[Y] * m - (2.0 * Entry->B[X] * Entry->D[X] + Entry->C[X] * Entry->C[X]) * Dy2;
-
- x1[3] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
-
- x1[4] = (Entry->D[Y] - P[Y]) * ((Entry->D[Y] - P[Y]) * r + 2.0 * D[Y] * m) + Dy2 * (P[X] * P[X] + P[Z] * P[Z] - Entry->D[X] * Entry->D[X]);
-
- n1 = Solve_Polynomial(4, x1, y1, Test_Flag(Lathe, STURM_FLAG), 0.0);
-
- break;
-
- /***********************************************************************
- * Cubic spline.
- ************************************************************************/
-
- case CUBIC_SPLINE:
-
- /* Solve 6th order polynomial. */
-
- x1[0] = Entry->A[Y] * Entry->A[Y] * r - Entry->A[X] * Entry->A[X] * Dy2;
-
- x1[1] = 2.0 * (Entry->A[Y] * Entry->B[Y] * r - Entry->A[X] * Entry->B[X] * Dy2);
-
- x1[2] = (2.0 * Entry->A[Y] * Entry->C[Y] + Entry->B[Y] * Entry->B[Y]) * r - (2.0 * Entry->A[X] * Entry->C[X] + Entry->B[X] * Entry->B[X]) * Dy2;
-
- x1[3] = 2.0 * ((Entry->A[Y] * Entry->D[Y] + Entry->B[Y] * Entry->C[Y] - Entry->A[Y] * P[Y]) * r + Entry->A[Y] * D[Y] * m - (Entry->A[X] * Entry->D[X] + Entry->B[X] * Entry->C[X]) * Dy2);
-
- x1[4] = (2.0 * Entry->B[Y] * (Entry->D[Y] - P[Y]) + Entry->C[Y] * Entry->C[Y]) * r + 2.0 * Entry->B[Y] * D[Y] * m - (2.0 * Entry->B[X] * Entry->D[X] + Entry->C[X] * Entry->C[X]) * Dy2;
-
- x1[5] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
-
- x1[6] = (Entry->D[Y] - P[Y]) * ((Entry->D[Y] - P[Y]) * r + 2.0 * D[Y] * m) + Dy2 * (P[X] * P[X] + P[Z] * P[Z] - Entry->D[X] * Entry->D[X]);
-
- n1 = Solve_Polynomial(6, x1, y1, Test_Flag(Lathe, STURM_FLAG), 0.0);
-
- break;
- }
-
- /* Test roots for valid intersections. */
-
- while (n1--)
- {
- w = y1[n1];
-
- if ((w >= 0.0) && (w <= 1.0))
- {
- if (fabs(D[Y]) > EPSILON)
- {
- k = (w * (w * (w * Entry->A[Y] + Entry->B[Y]) + Entry->C[Y]) + Entry->D[Y] - P[Y]) / D[Y];
-
- if (test_hit(Lathe, Ray, Depth_Stack, k / len, w, intervals[j].n))
- {
- found = TRUE;
-
- if (k < best)
- {
- best = k;
- }
- }
- }
- else
- {
- k = w * (w * (w * Entry->A[X] + Entry->B[X]) + Entry->C[X]) + Entry->D[X];
-
- x2[0] = r;
- x2[1] = 2.0 * m;
-
- x2[2] = P[X] * P[X] + P[Z] * P[Z] - k * k;
-
- n2 = Solve_Polynomial(2, x2, y2, FALSE, 0.0);
-
- while (n2--)
- {
- k = y2[n2];
-
- if (test_hit(Lathe, Ray, Depth_Stack, k / len, w, intervals[j].n))
- {
- found = TRUE;
-
- if (k < best)
- {
- best = k;
- }
- }
- }
- }
- }
- }
- }
-
- return(found);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Inside_Lathe
- *
- * INPUT
- *
- * IPoint - Intersection point
- * Object - Object
- *
- * OUTPUT
- *
- * RETURNS
- *
- * int - TRUE if inside
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Test if a point lies inside the lathe.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- static int Inside_Lathe(IPoint, Object)
- VECTOR IPoint;
- OBJECT *Object;
- {
- int i, n, NC;
- DBL r, k, w;
- DBL x[4], y[3];
- DBL *height, *radius;
- VECTOR P;
- BCYL_ENTRY *entry;
- LATHE_SPLINE_ENTRY *Entry;
- LATHE *Lathe = (LATHE *)Object;
-
- height = Lathe->Spline->BCyl->height;
-
- radius = Lathe->Spline->BCyl->radius;
-
- entry = Lathe->Spline->BCyl->entry;
-
- /* Transform the point into the lathe space. */
-
- MInvTransPoint(P, IPoint, Lathe->Trans);
-
- /* Number of crossings. */
-
- NC = 0;
-
- if ((P[Y] >= Lathe->Height1) && (P[Y] <= Lathe->Height2))
- {
- r = sqrt(P[X] * P[X] + P[Z] * P[Z]);
-
- if ((r >= Lathe->Radius1) && (r <= Lathe->Radius2))
- {
- for (i = 0; i < Lathe->Number; i++)
- {
- Entry = &Lathe->Spline->Entry[i];
-
- /* Test if we are inside the segments cylindrical bound. */
-
- if ((P[Y] >= height[entry[i].h1] - EPSILON) &&
- (P[Y] <= height[entry[i].h2] + EPSILON))
- {
- x[0] = Entry->A[Y];
- x[1] = Entry->B[Y];
- x[2] = Entry->C[Y];
- x[3] = Entry->D[Y] - P[Y];
-
- n = Solve_Polynomial(3, x, y, Test_Flag(Lathe, STURM_FLAG), 0.0);
-
- while (n--)
- {
- w = y[n];
-
- if ((w >= 0.0) && (w <= 1.0))
- {
- k = w * (w * (w * Entry->A[X] + Entry->B[X]) + Entry->C[X]) + Entry->D[X] - r;
-
- if (k >= 0.0)
- {
- NC++;
- }
- }
- }
- }
- }
- }
- }
-
- if (NC & 1)
- {
- return(!Test_Flag(Lathe, INVERTED_FLAG));
- }
- else
- {
- return(Test_Flag(Lathe, INVERTED_FLAG));
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Lathe_Normal
- *
- * INPUT
- *
- * Result - Normal vector
- * Object - Object
- * Inter - Intersection found
- *
- * OUTPUT
- *
- * Result
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the normal of the lathe in a given point.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- static void Lathe_Normal(Result, Object, Inter)
- OBJECT *Object;
- VECTOR Result;
- INTERSECTION *Inter;
- {
- DBL r, dx, dy;
- VECTOR P, N;
- LATHE *Lathe = (LATHE *)Object;
- LATHE_SPLINE_ENTRY *Entry;
-
- Entry = &Lathe->Spline->Entry[Inter->i1];
-
- /* Transform the point into the lathe space. */
-
- MInvTransPoint(P, Inter->IPoint, Lathe->Trans);
-
- /* Get distance from rotation axis. */
-
- r = P[X] * P[X] + P[Z] * P[Z];
-
- if (r > EPSILON)
- {
- r = sqrt(r);
-
- /* Get derivatives. */
-
- dx = Inter->d1 * (3.0 * Entry->A[X] * Inter->d1 + 2.0 * Entry->B[X]) + Entry->C[X];
- dy = Inter->d1 * (3.0 * Entry->A[Y] * Inter->d1 + 2.0 * Entry->B[Y]) + Entry->C[Y];
-
- /* Get normal by rotation. */
-
- N[X] = dy * P[X];
- N[Y] = -dx * r;
- N[Z] = dy * P[Z];
- }
- else
- {
- N[X] = N[Z] = 0.0; N[Y] = 1.0;
- }
-
- /* Transform the normalt out of the lathe space. */
-
- MTransNormal(Result, N, Lathe->Trans);
-
- VNormalize(Result, Result);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Translate_Lathe
- *
- * INPUT
- *
- * Object - Object
- * Vector - Translation vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Translate a lathe.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- static void Translate_Lathe(Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Lathe(Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Rotate_Lathe
- *
- * INPUT
- *
- * Object - Object
- * Vector - Rotation vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Rotate a lathe.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- static void Rotate_Lathe(Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Lathe(Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Scale_Lathe
- *
- * INPUT
- *
- * Object - Object
- * Vector - Scaling vector
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Scale a lathe.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- static void Scale_Lathe(Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Lathe(Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Transform_Lathe
- *
- * INPUT
- *
- * Object - Object
- * Trans - Transformation to apply
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Transform a lathe and recalculate its bounding box.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- static void Transform_Lathe(Object, Trans)
- OBJECT *Object;
- TRANSFORM *Trans;
- {
- Compose_Transforms(((LATHE *)Object)->Trans, Trans);
-
- Compute_Lathe_BBox((LATHE *)Object);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Invert_Lathe
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Invert a lathe.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- static void Invert_Lathe(Object)
- OBJECT *Object;
- {
- Invert_Flag(Object, INVERTED_FLAG);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Lathe
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * LATHE * - new lathe
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Create a new lathe.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- LATHE *Create_Lathe()
- {
- LATHE *New;
-
- New = (LATHE *)POV_MALLOC(sizeof(LATHE), "lathe");
-
- INIT_OBJECT_FIELDS(New,LATHE_OBJECT,&Lathe_Methods)
-
- New->Trans = Create_Transform();
-
- New->Spline_Type = LINEAR_SPLINE;
-
- New->Number = 0;
-
- New->Spline = NULL;
-
- New->Radius1 =
- New->Radius2 =
- New->Height1 =
- New->Height2 = 0.0;
-
- return(New);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Copy_Lathe
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * RETURNS
- *
- * void * - New lathe
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Copy a lathe structure.
- *
- * NOTE: The splines are not copied, only the number of references is
- * counted, so that Destray_Lathe() knows if they can be destroyed.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- * Sep 1994 : Fixed memory leakage bug. [DB]
- *
- ******************************************************************************/
-
- static void *Copy_Lathe(Object)
- OBJECT *Object;
- {
- LATHE *New, *Lathe = (LATHE *)Object;
-
- New = Create_Lathe();
-
- /* Get rid of the transformation created in Create_Lathe(). */
-
- Destroy_Transform(New->Trans);
-
- /* Copy lathe. */
-
- *New = *Lathe;
-
- New->Trans = Copy_Transform(Lathe->Trans);
-
- New->Spline->References++;
-
- return(New);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_Lathe
- *
- * INPUT
- *
- * Object - Object
- *
- * OUTPUT
- *
- * Object
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Destroy a lathe.
- *
- * NOTE: The splines are destroyed if they are no longer used by any copy.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- * Oct 1996 : Changed code to include faster version. [DB]
- *
- ******************************************************************************/
-
- static void Destroy_Lathe(Object)
- OBJECT *Object;
- {
- LATHE *Lathe = (LATHE *)Object;
-
- Destroy_Transform(Lathe->Trans);
-
- if (--(Lathe->Spline->References) == 0)
- {
- Destroy_BCyl(Lathe->Spline->BCyl);
-
- POV_FREE(Lathe->Spline->Entry);
-
- POV_FREE(Lathe->Spline);
- }
-
- POV_FREE (Object);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Lathe_BBox
- *
- * INPUT
- *
- * Lathe - Lathe
- *
- * OUTPUT
- *
- * Lathe
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the bounding box of a lathe.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- *
- ******************************************************************************/
-
- void Compute_Lathe_BBox(Lathe)
- LATHE *Lathe;
- {
- Make_BBox(Lathe->BBox, -Lathe->Radius2, Lathe->Height1, -Lathe->Radius2,
- 2.0 * Lathe->Radius2, Lathe->Height2 - Lathe->Height1, 2.0 * Lathe->Radius2);
-
- Recompute_BBox(&Lathe->BBox, Lathe->Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Compute_Lathe
- *
- * INPUT
- *
- * Lathe - Lathe
- * P - Points defining lathe
- *
- * OUTPUT
- *
- * Lathe
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Calculate the spline segments of a lathe from a set of points.
- *
- * Note that the number of points in the lathe has to be set.
- *
- * CHANGES
- *
- * Jun 1994 : Creation.
- * Oct 1996 : Changed code to include faster version. [DB]
- *
- ******************************************************************************/
-
- void Compute_Lathe(Lathe, P)
- LATHE *Lathe;
- UV_VECT *P;
- {
- int i, n;
- DBL x[4], xmin, xmax;
- DBL y[4], ymin, ymax;
- DBL c[3], r[2];
- DBL *tmp_r1;
- DBL *tmp_r2;
- DBL *tmp_h1;
- DBL *tmp_h2;
- UV_VECT A, B, C, D;
-
- /* Allocate Lathe->Number segments. */
-
- if (Lathe->Spline == NULL)
- {
- Lathe->Spline = (LATHE_SPLINE *)POV_MALLOC(sizeof(LATHE_SPLINE), "spline segments of lathe");
-
- /* Init spline. */
-
- Lathe->Spline->References = 1;
-
- Lathe->Spline->Entry = (LATHE_SPLINE_ENTRY *)POV_MALLOC(Lathe->Number*sizeof(LATHE_SPLINE_ENTRY), "spline segments of lathe");
- }
- else
- {
- /* This should never happen! */
-
- Error("Lathe segments are already defined.\n");
- }
-
- /* Allocate temporary lists. */
-
- tmp_r1 = (DBL *)POV_MALLOC(Lathe->Number * sizeof(DBL), "temp lathe data");
- tmp_r2 = (DBL *)POV_MALLOC(Lathe->Number * sizeof(DBL), "temp lathe data");
- tmp_h1 = (DBL *)POV_MALLOC(Lathe->Number * sizeof(DBL), "temp lathe data");
- tmp_h2 = (DBL *)POV_MALLOC(Lathe->Number * sizeof(DBL), "temp lathe data");
-
- /***************************************************************************
- * Calculate segments.
- ****************************************************************************/
-
- /* We want to know the size of the overall bounding cylinder. */
-
- xmax = ymax = -BOUND_HUGE;
- xmin = ymin = BOUND_HUGE;
-
- for (i = 0; i < Lathe->Number; i++)
- {
- switch (Lathe->Spline_Type)
- {
- /*************************************************************************
- * Linear spline (nothing more than a simple polygon).
- **************************************************************************/
-
- case LINEAR_SPLINE:
-
- /* Use linear interpolation. */
-
- A[X] = 0.0;
- B[X] = 0.0;
- C[X] = -1.0 * P[i][X] + 1.0 * P[i+1][X];
- D[X] = 1.0 * P[i][X];
-
- A[Y] = 0.0;
- B[Y] = 0.0;
- C[Y] = -1.0 * P[i][Y] + 1.0 * P[i+1][Y];
- D[Y] = 1.0 * P[i][Y];
-
- /* Get maximum coordinates in current segment. */
-
- x[0] = x[2] = P[i][X];
- x[1] = x[3] = P[i+1][X];
-
- y[0] = y[2] = P[i][Y];
- y[1] = y[3] = P[i+1][Y];
-
- break;
-
-
- /*************************************************************************
- * Quadratic spline.
- **************************************************************************/
-
- case QUADRATIC_SPLINE:
-
- /* Use quadratic interpolation. */
-
- A[X] = 0.0;
- B[X] = 0.5 * P[i][X] - 1.0 * P[i+1][X] + 0.5 * P[i+2][X];
- C[X] = -0.5 * P[i][X] + 0.5 * P[i+2][X];
- D[X] = 1.0 * P[i+1][X];
-
- A[Y] = 0.0;
- B[Y] = 0.5 * P[i][Y] - 1.0 * P[i+1][Y] + 0.5 * P[i+2][Y];
- C[Y] = -0.5 * P[i][Y] + 0.5 * P[i+2][Y];
- D[Y] = 1.0 * P[i+1][Y];
-
- /* Get maximum coordinates in current segment. */
-
- x[0] = x[2] = P[i+1][X];
- x[1] = x[3] = P[i+2][X];
-
- y[0] = y[2] = P[i+1][Y];
- y[1] = y[3] = P[i+2][Y];
-
- break;
-
-
- /*************************************************************************
- * Cubic spline.
- **************************************************************************/
-
- case CUBIC_SPLINE:
-
- /* Use cubic interpolation. */
-
- A[X] = -0.5 * P[i][X] + 1.5 * P[i+1][X] - 1.5 * P[i+2][X] + 0.5 * P[i+3][X];
- B[X] = P[i][X] - 2.5 * P[i+1][X] + 2.0 * P[i+2][X] - 0.5 * P[i+3][X];
- C[X] = -0.5 * P[i][X] + 0.5 * P[i+2][X];
- D[X] = P[i+1][X];
-
- A[Y] = -0.5 * P[i][Y] + 1.5 * P[i+1][Y] - 1.5 * P[i+2][Y] + 0.5 * P[i+3][Y];
- B[Y] = P[i][Y] - 2.5 * P[i+1][Y] + 2.0 * P[i+2][Y] - 0.5 * P[i+3][Y];
- C[Y] = -0.5 * P[i][Y] + 0.5 * P[i+2][Y];
- D[Y] = P[i+1][Y];
-
- /* Get maximum coordinates in current segment. */
-
- x[0] = x[2] = P[i+1][X];
- x[1] = x[3] = P[i+2][X];
-
- y[0] = y[2] = P[i+1][Y];
- y[1] = y[3] = P[i+2][Y];
-
- break;
-
- default:
-
- Error("Unknown lathe type in Compute_Lathe().\n");
-
- }
-
- Assign_UV_Vect(Lathe->Spline->Entry[i].A, A);
- Assign_UV_Vect(Lathe->Spline->Entry[i].B, B);
- Assign_UV_Vect(Lathe->Spline->Entry[i].C, C);
- Assign_UV_Vect(Lathe->Spline->Entry[i].D, D);
-
- /* Get maximum coordinates in current segment. */
-
- c[0] = 3.0 * A[X];
- c[1] = 2.0 * B[X];
- c[2] = C[X];
-
- n = Solve_Polynomial(2, c, r, FALSE, 0.0);
-
- while (n--)
- {
- if ((r[n] >= 0.0) && (r[n] <= 1.0))
- {
- x[n] = r[n] * (r[n] * (r[n] * A[X] + B[X]) + C[X]) + D[X];
- }
- }
-
- c[0] = 3.0 * A[Y];
- c[1] = 2.0 * B[Y];
- c[2] = C[Y];
-
- n = Solve_Polynomial(2, c, r, FALSE, 0.0);
-
- while (n--)
- {
- if ((r[n] >= 0.0) && (r[n] <= 1.0))
- {
- y[n] = r[n] * (r[n] * (r[n] * A[Y] + B[Y]) + C[Y]) + D[Y];
- }
- }
-
- /* Set current segment's bounding cylinder. */
-
- tmp_r1[i] = min(min(x[0], x[1]), min(x[2], x[3]));
- tmp_r2[i] = max(max(x[0], x[1]), max(x[2], x[3]));
-
- tmp_h1[i] = min(min(y[0], y[1]), min(y[2], y[3]));
- tmp_h2[i] = max(max(y[0], y[1]), max(y[2], y[3]));
-
- /* Keep track of overall bounding cylinder. */
-
- xmin = min(xmin, tmp_r1[i]);
- xmax = max(xmax, tmp_r2[i]);
-
- ymin = min(ymin, tmp_h1[i]);
- ymax = max(ymax, tmp_h2[i]);
-
- /*
- fprintf(stderr, "bound spline segment %d: ", i);
- fprintf(stderr, "r = %f - %f, h = %f - %f\n", tmp_r1[i], tmp_r2[i], tmp_h1[i], tmp_h2[i]);
- */
- }
-
- /* Set overall bounding cylinder. */
-
- Lathe->Radius1 = xmin;
- Lathe->Radius2 = xmax;
-
- Lathe->Height1 = ymin;
- Lathe->Height2 = ymax;
-
- /* Get bounding cylinder. */
-
- Lathe->Spline->BCyl = Create_BCyl(Lathe->Number, tmp_r1, tmp_r2, tmp_h1, tmp_h2);
-
- /* Get rid of temp. memory. */
-
- POV_FREE(tmp_h2);
- POV_FREE(tmp_h1);
- POV_FREE(tmp_r2);
- POV_FREE(tmp_r1);
- }
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * test_hit
- *
- * INPUT
- *
- * Lathe - Pointer to lathe structure
- * Ray - Current ray
- * Depth_Stack - Current depth stack
- * d, w, n - Intersection depth, parameter and segment number
- *
- * OUTPUT
- *
- * Depth_Stack
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Test if a hit is valid and push if on the intersection depth.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
-
- static int test_hit(Lathe, Ray, Depth_Stack, d, w, n)
- LATHE *Lathe;
- RAY *Ray;
- ISTACK *Depth_Stack;
- DBL d, w;
- int n;
- {
- VECTOR IPoint;
-
- if ((d > DEPTH_TOLERANCE) && (d < Max_Distance))
- {
- VEvaluateRay(IPoint, Ray->Initial, d, Ray->Direction);
-
- if (Point_In_Clip(IPoint, ((OBJECT *)Lathe)->Clip))
- {
- push_entry_i1_d1(d, IPoint, (OBJECT *)Lathe, n, w, Depth_Stack);
-
- return(TRUE);
- }
- }
-
- return(FALSE);
- }
-
-
-
-